home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
gamesrc
/
wallgame
/
wall.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1991-02-07
|
18KB
|
765 lines
(***********************************************************************)
(* *)
(* WALLGAME *)
(* *)
(* A version of The Old Favorite - BREAKOUT *)
(* Copyright Jari Karjala 1987-1990 *)
(* *)
(* *)
(* This is a FreeWare Program. *)
(* You may copy it to your friends, but if *)
(* you change it, don't leave my name out. *)
(* This is not begware, so you need not pay *)
(* anything to play with this. *)
(* *)
(***********************************************************************)
{ This version will compile without changes only with Turbo Pascal 5.0. }
{ If you change something, please mark the changes clearly. }
{$R-,S-,I-,D-,A-,F-,V-,B+,L-,N- }
Uses
crt,dos;
const
Max_Wall = 10;
Max_His = 8;
Bonus_Brick = 10;
Extra_Ball_Brick = 11;
type
str20 = string[20];
walltype = array[0..7] of string[20];
AllWalls = array[1..max_wall] of record
wall:walltype;
msg:string[50];
count:integer
end;
HiScoresType = array [1..Max_His] of record
Name : str20;
Score : real;
end;
var
a,b,
max_walls_read,
Wall_no, Balls_left, Bricks_hit, Hit_Count, brick_hit_count,
Paddle_x, Paddle_move_dir,
Brick_x, Brick_y, Brick_move_dir, Brick_Type,
Sav_x_inc, Sav_y_inc, bonus,
Ball_x, Ball_y, Ball_x_inc, Ball_y_inc : integer;
Score : real;
Missed, May_Turn, FX, moving, Quiet, HasMouse : boolean;
walls : AllWalls;
wall : walltype;
HiScores : HiScoresType;
message : string[255];
mouse_x,mouse_y : word;
{ Procedures for direct handling of PCompatible hardware }
const
inverse = $70;
normal = $f;
screenseg : word = $B800;
bmax = 11;
{ 0 1 2 3 4 5 6 7 8 9 : ; < > ? @ A ... }
Bricks:array[0..bmax] of string[8] = (#32#7#32#7#32#7#32#7,
#178#$70#178#$70#178#$70#178#$70,
#177#$70#177#$70#177#$70#177#$70,
#176#$70#176#$70#176#$70#176#$70,
#219#$7#219#$7#219#$7#219#$7,
#176#$7f#176#$7f#176#$7f#176#$7f,
#177#$7f#177#$7f#177#$7f#177#$7f,
#178#$7f#178#$7f#178#$7f#178#$7f,
#219#$7f#219#$7f#219#$7f#219#$7f,
#$19#$70#$19#$70#$19#$70#$19#$70,
#219#$7#50#$70#88#$70#219#$7,
#66#$78#65#$78#76#$78#76#$78
);
{01234567890123}
Paddle:string[16] = ' ▀▀▀▀▀▀▀▀ ';
Empty_name:str20 = ' ';
Procedure InitHardWare;
var regs:registers;
begin
regs.ax:=0;
regs.bx:=0;
intr($33,regs);
if regs.ax<>0 then begin
HasMouse := true;
regs.ax:=2;
intr($33,regs); { hide cursor }
regs.ax:=4;
regs.cx := 40;
regs.dx := 0;
mouse_x := regs.cx;
mouse_y := regs.dx;
intr($33,regs); { set location }
regs.ax:=$f;
regs.cx := 2;
regs.dx := 20;
intr($33,regs); { set mickeys }
end
else
HasMouse := false;
if lastmode=mono then screenseg:=$B000 else screenseg:=$B800;
end;
Function Get_Brick(x,y:integer):integer;
{ Returns the number of the brick in given position. }
begin
x:=succ(x shr 4); y:=y shr 3;
Get_Brick:=ord(wall[y][x])-ord('0');
end;
Procedure Put_Brick(x,y,a:integer);
{ A=type of brick. If a=0 then brick is empty. }
{ X,Y are aligned to brick boundary. }
var
address,b:integer;
brk:string[8];
begin
address:=y shr 3 * 160 + x shr 1 and $F8;
brk:=bricks[a];
for b:=0 to 7 do mem[screenseg:address+b] := ord(brk[succ(b)]);
if y<64 then wall[y shr 3][succ(x shr 4)]:=chr(ord('0')+a);
end;
Procedure Put_Paddle(x:integer);
var
address,a,b:integer;
begin
address:=3680+x shr 1 and $FE - 2*3 { three spaces };
b := length(Paddle) - 1;
if address + b > 3680+160 then b := b - (address - 3680 - 160);
for a:=0 to b do
memw[screenseg:address+a shl 1] := ord(Paddle[succ(a)])+$F00;
end;
Procedure Put_Ball(x,y,color:integer);
{ If color is 0 then ball is erased. }
var
address:integer;
begin
address:=x shr 1 and $FE + y shr 3*160;
if color<>0 then
if odd(y shr 2) then mem[screenseg:address]:=220
else mem[screenseg:address]:=223
else mem[screenseg:address]:=32;
mem[screenseg:address+1]:=$F;
end;
Procedure WriteXY(x,y,attr:integer; str:string);
var
a,address:integer;
begin
address:=y*160 + x shl 1 - 2;
for a:=1 to length(str) do
memw[screenseg:address+a shl 1]:=attr shl 8 or ord(str[a]);
end;
procedure clrline(y:integer);
const line:string[80]=
' ';
begin
WriteXY(0,y,normal,line)
end;
procedure cls;
var
a:integer;
begin
for a:=24 downto 0 do clrline(a)
end;
Function Get_Direction:integer;
{ Returns value: -2 if left shift + alt
-1 if left shift
0 if nothing
1 if right shift
2 if right shift + alt
Halt, if Ctrl + Alt pressed. }
var
a,b:integer;
regs:registers;
begin
regs.ax:=$200;
intr(22,regs);
a:=regs.ax;
if a and 1 =1 then b:=1 else
if a and 2 =2 then b:=-1 else
b:=0;
if a and 8 =8 then b:=b shl 1;
if a and $c=$c then halt;
Get_direction:=b;
if HasMouse then begin
regs.ax:=3;
regs.cx:=0;
intr($33,regs); { get cursor }
if (regs.cx<>mouse_x) then begin
if (regs.cx > mouse_x) then begin
a := (regs.cx - mouse_x) div 2;
if a>6 then
a := 6;
end
else begin
a := -((mouse_x - regs.cx) div 2);
if a < -6 then
a := -6;
end;
regs.ax:=4;
regs.cx:=40;
mouse_x := regs.cx;
intr($33,regs); { set cursor }
Get_direction := a;
end;
end;
end;
Procedure Sound_on(f:integer);
begin
if not Quiet then Sound(f);
end;
Procedure Sound_off;
begin
nosound
end;
{******** Portable routines ********}
Procedure Beep(f,t:integer);
begin
Sound_on(f);
delay(t);
Sound_off
end;
function strs(a:real; b:integer):string;
var
s:string;
begin
str(a:b:0,s);
strs:=s;
end;
function sgn(a:integer):integer;
begin
if a<0 then sgn:=-1 else if a>0 then sgn:=1 else sgn:=0
end;
function exist(var a:text):boolean;
begin
{$I-}
reset(a);
{$I+}
exist:=(ioresult=0)
end;
Procedure Load_Walls;
var
a,b,c,d:integer;
source:text;
begin
assign(source,'WALL DAT.A');
if not exist(source) then
begin Writeln('ERROR: File WALL DAT.A not found.');halt end;
reset(source);
readln(source,message);
a:=1;
while not eof(source) and (a<=max_wall) do
with walls[a] do
begin
readln(source,msg);
for b:=0 to 7 do readln(source,wall[b]);
count:=0;
for c:=0 to 7 do
for d:=1 to 20 do
if wall[c][d]<>'0' then count:=succ(count);
a:=succ(a)
end;
max_walls_read:=pred(a);
close(source);
end;
procedure load_hiscores;
var
a,b:integer;
st:string[8];
source:text;
line:string[28];
begin
assign(source,'WALL SCO.RES');
if not exist(source) then
for a:=1 to max_his do
with HiScores[a] do
begin
name:='***** JPK *****';
score:=10000-1234*a;
end
else
begin
reset(source);
for a:=1 to max_his do
with HiScores[a] do
readln(source,name,score);
end;
close(source);
end;
procedure save_hiscores;
var
a,b:integer;
dest:text;
line:string[28];
begin
assign(dest,'WALL SCO.RES');
rewrite(dest);
for a:=1 to max_his do
with HiScores[a] do
writeln(dest,name,score:8:0);
close(dest);
end;
Procedure Print_HiScores;
var
a:integer;
begin
for a:=0 to 19 do
begin
put_brick(a shl 4,8,5);
put_brick(a shl 4,184,5);
put_brick(a shl 4,16,5);
put_brick(a shl 4,176,5);
put_brick(0,16+a shl 3,5);
put_brick(312,16+a shl 3,5);
end;
writexy(28,4,inverse,' WALLGAME Hall of Fame ');
for a:=1 to Max_His do
with HiScores[a] do
writexy(25,4+a shl 1,normal,copy(name+empty_name,1,20)+' '+strs(score,8));
end;
Procedure ReadNameXY(x,y,attr:integer; var st:str20);
var
a:integer;
ch:char;
begin
while keypressed do ch:=readkey;
a:=1;
writexy(x,y,attr,st);
repeat
ch:=readkey;
if (ch>chr(31))and(a<21) then
begin
st[a]:=ch;
a:=a+1;
writeXY(x+a-2,y,attr,ch);
end
else
if ch=^H then
if a>1 then
begin
a:=pred(a);
st[a]:=' ';
writexy(x,y,attr,st);
end
until ch=^M;
if st=Empty_Name then
st:=' Unknown ';
end;
procedure Insert_HiScore(sc:real);
var
a,b:integer;
begin
a:=max_his;
while (sc>HiScores[a].score) and (a>1) do a:=pred(a);
if sc<HiScores[1].score then a:=succ(a);
for b:=pred(max_his) downto a do
HiScores[succ(b)]:=HiScores[b];
HiScores[a].score:=sc;
HiScores[a].name:=Empty_name;
cls;
Writexy(15,24,inverse,'CONGRATULATIONS -- You made it into Hall of Fame');
Print_HiScores;
ReadNameXY(25,4+a shl 1,inverse,HiScores[a].name);
Save_HiScores;
end;
procedure Print_Wall;
var
a,b:integer;
begin
Cls;
wall:=walls[wall_no].wall;
for a:=0 to 7 do
for b:=0 to 19 do
put_brick(b*16,a*8,ord(wall[a][succ(b)])-ord('0'));
bricks_hit:=0;
end;
Procedure pause(b:integer);
var
a:integer;
begin
a:=0;
while (a<b) and (abs(Get_Direction)<>1) do
begin
a:=a+1;
delay(1);
end;
end;
procedure Scroll_message;
begin
writeXY(0,0,normal,copy(message,1,80));
message:=copy(message,2,length(message))+message[1];
beep(1000,1);
delay(100);
end;
Procedure Init_All;
begin
InitHardware;
Cls;
Load_Walls;
Load_HiScores;
end;
procedure Init_Game;
var
a:integer;
begin
Clrline(24);
WriteXY(19,24,inverse,' Press Shift to start, Ctrl+Alt to end. ');
Print_HiScores;
repeat
Scroll_message;
until abs(get_direction)>0;
wall_no:=1;
if get_direction=2 then begin
write('Press enter');
a:=ord(readkey)-ord('0'); if a>0 then wall_no:=a;
end;
balls_left:=5;
score:=0;
Cls;
Print_Wall;
gotoxy(1,25);
end;
procedure Init_Specials;
begin
moving:=false;
hit_count:=0;
bonus:=1;
end;
procedure Init_Ball;
begin
WriteXY(2,24,normal,' SCORE '+strs(score,7)+' BALLS'+strs(balls_left,2));
writexy(0,24,inverse,strs(1 shl pred(bonus),1)+'X');
WriteXY(30,24,normal,walls[wall_no].msg);
Paddle_x:=130;
Ball_x:=80+random(160);
Ball_y:=100;
if random(2)=1 then Ball_x_inc:=4 else Ball_x_inc:=-4;
Ball_y_inc:=2;
Missed:=false;
May_Turn:=true;
FX:=false;
put_ball(ball_x,ball_y,1);
put_paddle(paddle_x);
for a:=500 to 1000 do
begin sound_on(a); delay(1) end;
beep(300,50);
brick_hit_count:=0;
end;
Procedure End_Move;
begin
if moving then put_brick(brick_x,brick_y,0);
moving:=false;
end;
Procedure End_Short_Special;
{ End special effects which work only until first hit into the paddle. }
begin
if Paddle_move_dir>0 then Ball_x_inc:=4 else Ball_x_inc:=-4;
Ball_y_inc:=2;
Sound_off;
FX:=false;
end;
Procedure End_Ball;
{ End special effects which work until the ball is missed. }
begin
clrline(23); Beep(100,400);
end_move;
Sound_off;
end;
Procedure Do_Shooter;
begin
ball_y_inc:=11-Ball_y shr 3;
Ball_x_inc:=0;
fx:=true;
end;
Procedure Do_bonus;
begin
end_move;
brick_hit_count:=0;
if bonus<5 then bonus:=succ(bonus);
writexy(0,24,inverse,strs(1 shl pred(bonus),1)+'X');
end;
Procedure Do_Extra_Ball;
begin
end_move;
hit_count:=0;
balls_left:=succ(balls_left);
writexy(24,24,normal,strs(balls_left,2));
end;
Procedure Move_Paddle;
var
a:integer;
begin
a:=Get_Direction;
if a=0 then
Paddle_Move_Dir:=0
else
begin
if a>0 then
if Paddle_x+a<284 then Paddle_Move_Dir:=a
else Paddle_Move_Dir:=284-Paddle_x
else
if Paddle_x+a>0 then Paddle_Move_Dir:=a
else Paddle_Move_Dir:= -Paddle_x;
if HasMouse then
Paddle_x:=Paddle_x+Paddle_Move_Dir
else
Paddle_x:=Paddle_x+Paddle_Move_Dir shl 1;
end;
Put_Paddle(Paddle_x);
end;
Procedure Start_Moving(brk:integer);
begin
moving:=true;
brick_x:=paddle_x shr 1 + 80; brick_y:=0;
if get_brick(brick_x,0)<>0 then brick_x:=0;
if sgn(paddle_move_dir)>0 then brick_move_dir:=1 else brick_move_dir:=-1;
Brick_type:=brk;
end;
Procedure Move_Brick;
var
a:integer;
begin
if brick_x<303 then
if brick_x>16 then
if get_brick((brick_x+brick_move_dir shl 4), brick_y)=0 then
begin
a:=brick_x;
brick_x:=brick_x+brick_move_dir;
put_brick(brick_x, brick_y, brick_type);
if brick_x shr 4<>a shr 4 then put_brick(a, brick_y, 0);
end
else
brick_move_dir:=-brick_move_dir
else
begin
brick_move_dir:=-brick_move_dir;
brick_x:=17;
end
else
begin
brick_move_dir:=-brick_move_dir;
brick_x:=302;
end;
end;
procedure move_bricks;
begin
If moving then
Move_brick
else
if brick_hit_count > 40 then
begin
if bonus<5 then
Start_moving(Bonus_brick)
end
else
if hit_count > 100 then
Start_moving(Extra_Ball_Brick)
else
delay(2);
end;
Procedure Move_Ball;
var
a,tx,ty,brick:integer;
begin
{*** Hit into Side Walls ***}
tx:=Ball_x+Ball_x_inc;
if tx>319 then
begin
Ball_x_inc:=-Ball_x_inc;
tx:=319;
ty:=ty and $fc
end else
if tx<0 then
begin
ball_x_inc:=-ball_x_inc;
tx:=0;
ty:=ty and $fc
end;
{*** Hit into Paddle or Roof ***}
ty:=Ball_y+Ball_y_inc;
if ty>183 then
if (tx>=Paddle_x) and (tx<=Paddle_x+40) then
begin
if FX then End_Short_Special;
Ball_y_inc:=-Ball_y_inc;
if Paddle_move_dir<>0 then
if sgn(paddle_move_dir)=sgn(ball_x_inc) then
begin
ball_y_inc:=pred(ball_y_inc);
if ball_y_inc<-4 then
begin
ball_y_inc:=-4;
end;
end
else
begin
ball_y_inc:=succ(ball_y_inc);
if ball_y_inc>-1 then
begin
ball_y_inc:=-1;
end;
end;
ty:=183;
beep(200,5);
if not moving then
begin
brick_hit_count:=succ(brick_hit_count);
hit_count:=succ(hit_count);
end
end
else
begin
Missed:=true;
Balls_Left:=Pred(Balls_Left);
end
else
if ty<0 then
begin
ball_y_inc:=-ball_y_inc;
ty:=0;
end;
{*** Hit into Brick ***}
if ty<64 then
begin
brick:=get_brick(tx,ty);
if brick<>0 then
begin
Put_Brick(tx,ty,0);
score:=score+brick shl bonus;
WriteXY(9,24,normal,strs(score,7));
if brick<10 then
begin
bricks_hit:=succ(bricks_hit);
if bricks_hit>=walls[wall_no].count then
begin
for a:=300 to 500 do beep(a,2);
wall_no:=succ(wall_no);
if wall_no>max_walls_read then wall_no:=1;
print_wall;
init_ball;
exit;
end;
if may_turn or (ball_y_inc>0) then Ball_y_inc:=-Ball_y_inc;
may_turn:=false;
ty:=ty and $f8+7;
if brick=9 then Do_Shooter;
end
else
Case brick of
Bonus_Brick : Do_Bonus;
Extra_Ball_Brick : Do_extra_ball;
else beep(1000+200*brick,200)
end;
beep(440+70*brick,10);
end else may_turn:=true;
end;
if fx then sound_on(400+ball_y*100);
Put_Ball(tx,ty,1);
if (tx shr 2 <> ball_x shr 2) or (ty shr 3 <> ball_y shr 3)
then Put_Ball(ball_x,ball_y,0);
Ball_x:=tx; Ball_y:=ty;
end;
Procedure Game_Over;
var
a:integer;
begin
for a:=22 downto 9 do
begin
sound_on(40*a);
WriteXY(29,a,inverse,'>>>> Game Over <<<<');
delay(50);
sound_on(40*a+20);
clrline(succ(a))
end;
for a:=44 to 88 do beep(a*10,5);
end;
{ ***** Main loop ***** }
begin
if paramstr(1)='/q' then Quiet := true else Quiet := false;
Init_All;
repeat
Init_Game;
repeat
Init_Specials;
Init_Ball;
repeat
Move_Paddle;
Move_Ball;
Move_Paddle;
Move_Bricks;
Delay(30);
until Missed;
End_Ball;
until Balls_left=0;
Game_Over;
if Score>HiScores[max_his].score then
Insert_HiScore(Score)
else
begin
Pause(5000);
cls;
end;
until false;
end.